package puzzle.slilin2.solver;

import puzzle.common.point.Direction;
import puzzle.common.point.Pnt;
import puzzle.common.point.Vct;
import puzzle.slilin2.data.CellType;
import puzzle.slilin2.data.SlilinBoard;

class ThreePairInitialRule extends SlilinCellRule {

	@Override
	protected CellType appliedCellType() {
		return CellType.NUMBER;
	}
	
	@Override
	protected boolean skipOutside() {
		return true;
	}
	
	@Override
	protected boolean skipUnmodifiedCell() {
		return true;
	}
	
	public boolean apply(SlilinBoard b, Pnt p0) {
		if (b.getNumber(p0) != 3) return false;

		boolean isChanged = false;
		isChanged |= processDirect(b, p0, Direction.E.v);
		isChanged |= processDirect(b, p0, Direction.S.v);
		isChanged |= processCorner(b, p0, Direction.NE.v, Direction.S.v);
		isChanged |= processCorner(b, p0, Direction.SE.v, Direction.W.v);
		return isChanged;
	}

	private boolean processDirect(SlilinBoard b, Pnt p0, Vct v) {
		if (b.getNumber(p0.add(v, 2)) != 3) {
			return false;
		}

		boolean isChanged = false;
		isChanged |= b.getLineCellState(p0.add(v, -1)).setExists(true);
		isChanged |= b.getLineCellState(p0.add(v, 1)).setExists(true);
		isChanged |= b.getLineCellState(p0.add(v, 3)).setExists(true);
		isChanged |= b.getLineCellState(p0.add(v, 1).add(v.lrot(), 2))
				.setForbidden(true);
		isChanged |= b.getLineCellState(p0.add(v, 1).add(v.rrot(), 2))
				.setForbidden(true);
		return isChanged;
	}

	private boolean processCorner(SlilinBoard b, Pnt p0, Vct v, Vct w) {
		Pnt p1 = p0;
		while (true) {
			p1 = p1.add(v, 2);
			switch (b.getNumber(p1)) {
			case 2:
				continue;
			case 3:
				break;
			default:
				return false;
			}
			break;
		}

		boolean isChanged = false;
		isChanged |= b.getLineCellState(p0.add(w)).setExists(true);
		isChanged |= b.getLineCellState(p0.add(w.rrot())).setExists(true);
		isChanged |= b.getLineCellState(p1.add(w.inv())).setExists(true);
		isChanged |= b.getLineCellState(p1.add(w.lrot())).setExists(true);
		return isChanged;
	}



}
